#ifndef ENGINE_TIMER_TASK_H
#define ENGINE_TIMER_TASK_H

#include "engine/result_codes.h"
#include "engine/kernel.h"
#include "engine/game_state.h"
#include "engine/task.h"

#include "boost/date_time/posix_time/posix_time.hpp"

using namespace boost::posix_time;

namespace engine {

class TimerTask : public Task {
public:
    TimerTask(GameState & game_state) : Task(kMaxUInt64), game_state_(game_state) {}

    virtual int Start() {
        //zero out the running total;
        total_elapsed_time_ = time_duration();

        //start the clock
        current_time_ = microsec_clock::universal_time();

        return base::OK_OK;
    }

    virtual int Update() {
        if(game_state_.test(GAME_FINISHED)) {
            SetCanKill(true);
            return base::OK_FALSE;
        } 

        //grab the current time
        ptime clock(microsec_clock::universal_time());

        bool game_paused = game_state_.test(GAME_PAUSED);
        if(!game_paused) {       
            //calculate the elapsed time
            elapsed_time_ = clock - current_time_;

            //update the running total
            total_elapsed_time_ += elapsed_time_;
        } else {
            //we are paused, so no time has elapsed
            //set elapsed_time_ to 0
            elapsed_time_ = time_duration();
        }

        //and finally update the current time;
        current_time_ = clock;

        if(game_paused)
            return base::OK_FALSE;
        else return base::OK_TRUE;
    }

    virtual int Stop() {return base::OK_OK;}

    virtual int OnResume() {
        current_time_ = microsec_clock::universal_time();
        return base::OK_OK;
    }

    
    int64 GetElapsedMicroseconds() const {
        return elapsed_time_.total_microseconds();
    }

    int64 GetTotalMicroseconds() const {
        return total_elapsed_time_.total_microseconds();
    }

    double GetElapsedSeconds() const {
        return GetElapsedMicroseconds() / 1000000.0;
    }

    double GetTotalSeconds() const {
        return GetTotalMicroseconds() / 1000000.0;
    }
 
protected:
    GameState & game_state_;
private:

    ptime current_time_;
    time_duration elapsed_time_;
    time_duration total_elapsed_time_;
}; //class TimerTask



class CountDownTask : public TimerTask{
public:
    CountDownTask (GameState & game_state, const int64 & microseconds) 
        : TimerTask(game_state), remaining_time_(microseconds) {
    }

    int Update() {
            int result;
        
            result = TimerTask::Update();

            remaining_time_ -= TimerTask::GetElapsedMicroseconds();
            if(remaining_time_ <= 0)
                SetCanKill(true);

            return result;
    }

    int Stop() {
        game_state_.set(GAME_FINISHED, true);

        return base::OK_FALSE;
    }

    int64 GetRemainingMicroseconds() {
        return remaining_time_;
    }

    double GetRemainingSeconds() {
        return remaining_time_ / 1000000.0;
    }
private:
    int64 remaining_time_;

}; //class CountDownTask

} //namespace engine
#endif //ENGINE_TIMER_TASK_H